#import "RNAddItemViewController.h"
#import "RNFilteringArrayController.h"
#import "MainWindowController.h"
#import "RNNewItemSheetController.h"
#import "RNSearchMenuView.h"
#import "RNSearchWindow.h"
#import "RNConstants.h"
#import "DetailViewController.h"
#import "Item.h"
#import "ListItem.h"
#import <SRStyledPopUpButton/SRStyledPopUpButton.h>

NSInteger const RNAddItemMaxSearchMenuItems = 10;
CGFloat const RNSearchMenuWidth = 250.0f;
CGFloat const RNSearchWindowXOffset = 102.0f;
NSString* const RNSearchWindowNoItemsFoundString = @"No items found";
NSString* const RNSearchWindowExcessItemsString = @" more…";
NSString* const RNSearchWindowCreateNewItemString = @"Create new item…";


@interface RNAddItemViewController (RNAddItemViewControllerPrivateMethods)
-(void)displaySearchMenu_;
-(void)removeSearchMenu_;
-(void)removeSearchField_;
-(void)resetRowCount_;
-(void)resizeSearchMenu_;
-(void)addSelectedItem_;
-(void)executeMenuExtraAtRow:(NSInteger)row forSearchString:(NSString *)searchString;
@end


@implementation RNAddItemViewController

@synthesize storesPopup = storesPopup_;
@synthesize searchField = searchField_;
@synthesize searchMenu = searchMenu_;
@synthesize searchWindow = searchWindow_;
@synthesize filteredItemsArrayController = filteredItemsController_;
@synthesize tableRows = tableRows_;
@synthesize menuExtras = menuExtras_;
@synthesize displayingMenu = displayingMenu_;

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle windowController:(XSWindowController *)windowController managedObjectContext:(NSManagedObjectContext *)managedObjectContext {
    if (!(self = [super initWithNibName:name bundle:bundle windowController:windowController managedObjectContext:managedObjectContext]))
        return nil;
    
    [self setSearchMenu:[[RNSearchMenuView alloc] initWithFrame:NSZeroRect]];
    [[self searchMenu] setAction:@selector(searchMenuClicked:)];
    [[self searchMenu] setTarget:self];
    [[self searchMenu] setDelegate:self];
    
    [self setSearchWindow:[[RNSearchWindow alloc] init]];
    [[[self searchWindow] contentView] addSubview:[self searchMenu]];
    return self;
}

-(void)awakeFromNib {
    [[[self searchField] cell] setSearchButtonCell:nil];
    [[self filteredItemsArrayController] setMaxItems:10];
    NSMutableArray *descriptors = [NSMutableArray array];
    [descriptors addObject:[[NSSortDescriptor alloc] initWithKey:@"confidence" ascending:NO]];
    [descriptors addObject:[[NSSortDescriptor alloc] initWithKey:@"favorite" ascending:NO]];
    [[self filteredItemsArrayController] setSortDescriptors:descriptors];
//    [[NSApp mainWindow] makeFirstResponder:[self searchField]];
}

// For the stores popup
-(NSArray *)titleDescriptors {
    return [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:RNTitleKey ascending:YES]];
}

-(void)mainWindowDidResize:(NSNotification *)note {
    [self removeSearchMenu_];
}


#pragma mark -
#pragma mark Actions

-(IBAction)setFocusOnSearchField:(id)sender {
    [[NSApp mainWindow] makeFirstResponder:[self searchField]];
}

-(IBAction)searchMenuClicked:(id)sender {
    [self addSelectedItem_];
}

-(IBAction)searchStringChanged:(id)sender {
    NSString *searchString = [[self searchField] stringValue];
    
    // If search string is blank, remove the search menu
    if ([searchString length] == 0) {
        if ([self displayingMenu])
            [self removeSearchMenu_];
        return;
    }
    
    // Display the search menu if necessary
    if (![self displayingMenu]) 
        [self displaySearchMenu_];
    
    NSManagedObject *list = [(DetailViewController *)[self parent] rootObject];
    [[self filteredItemsArrayController] filterWithString:searchString withCurrentItems:[[list valueForKeyPath:@"items.item"] allObjects]];
    
    // Update the search items
    [self resetRowCount_];
    [[self searchMenu] update];
    
    // Resize search window to fit items
    CGFloat heightNeeded = [[self searchMenu] preferredHeight];
    NSPoint searchWindowOriginBase = [[self view] convertPoint:NSMakePoint(NSMinX([[self view] bounds]), NSMaxY([[self view] bounds])) toView:nil]; // Window coordinates
    NSPoint searchWindowOrigin = [[NSApp mainWindow] convertBaseToScreen:searchWindowOriginBase];       // Screen coordinates
    NSRect searchWindowFrame = NSMakeRect(searchWindowOrigin.x + RNSearchWindowXOffset, searchWindowOrigin.y - heightNeeded, RNSearchMenuWidth, heightNeeded);
    [[self searchWindow] setFrame:searchWindowFrame display:YES];
}

-(void)addSelectedItem_ {
    [self removeSearchMenu_];
    NSString *searchString = [[self searchField] stringValue];
    
    NSInteger row = [[self searchMenu] selectedRow];
    if (row < 0)
        return;
    
    NSInteger itemsCount = [[[self filteredItemsArrayController] arrangedObjects] count];
    if (row >= itemsCount) {
        [self executeMenuExtraAtRow:(row - itemsCount) forSearchString:searchString];
        [[self searchField] setStringValue:@""];
        return;
    }
    [[self searchField] setStringValue:@""];
    Item *selectedItem = [[[self filteredItemsArrayController] arrangedObjects] objectAtIndex:row];
    List *selectedList = [(DetailViewController *)[self parent] rootObject];
    
    ListItem *newListItem = [NSEntityDescription insertNewObjectForEntityForName:RNEntityNameListItem inManagedObjectContext:[self managedObjectContext]];
    [newListItem setItem:selectedItem];
    [newListItem setCategory:[selectedItem category]];
    [newListItem addAisles:[selectedItem aisles]];
    [newListItem setList:selectedList];
}

-(void)executeMenuExtraAtRow:(NSInteger)row forSearchString:(NSString *)searchString {
    if (row < 0 || row >= [[self menuExtras] count])
        return;
    NSString *selectedItem = [[self menuExtras] objectAtIndex:row];
    if ([selectedItem isEqualToString:RNSearchWindowCreateNewItemString]) {
        MainWindowController *windowController = [[NSApp mainWindow] windowController];
        NSAssert([windowController isKindOfClass:[MainWindowController class]], @"RNAddItemViewController:executeMenuExtraAtRow: windowController not of class MainWindowController");
        RNNewItemSheetController *newItemSheetController = [windowController newItemSheetController];
//        [newItemSheetController window];
//        [newItemSheetController selectItemWithTag:RNNewItemSheetItemToolbarItem];
//        [[newItemSheetController itemViewNameField] setStringValue:searchString];
//        [newItemSheetController displayNewItemSheet];
        [newItemSheetController createItemWithString:searchString addToList:[(DetailViewController *)[self parent] rootObject]];
    }
    if ([selectedItem rangeOfString:RNSearchWindowExcessItemsString].location != NSNotFound) {
        [NSApp sendAction:@selector(searchWithAddItemString:) to:nil from:[self searchField]];
    }
}

-(void)displaySearchMenu_ {
    [self setDisplayingMenu:YES];
    [[NSApp mainWindow] addChildWindow:[self searchWindow] ordered:NSWindowAbove];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mainWindowDidResize:) name:NSWindowDidResizeNotification object:[NSApp mainWindow]];
}

-(void)removeSearchMenu_ {
    [self setDisplayingMenu:NO];
    [[NSApp mainWindow] removeChildWindow:[self searchWindow]];
    [[self searchWindow] orderOut:self];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:nil];
}

-(void)removeSearchField_ {
    [[self view] removeFromSuperview];
    [[self searchField] setStringValue:@""];
}

-(void)resetRowCount_ {
    NSUInteger rowCount = [[[self filteredItemsArrayController] arrangedObjects] count];
    NSMutableArray *extras = [NSMutableArray array];
    if (rowCount == 0) 
        [extras addObject:RNSearchWindowNoItemsFoundString];
    NSUInteger excessItems = [[self filteredItemsArrayController] excessItems];
    if (excessItems > 0)
        [extras addObject:[NSString stringWithFormat:@"   %i%@", excessItems, RNSearchWindowExcessItemsString]];
    [extras addObject:[RNSearchMenuSeparatorItem copy]];
    [extras addObject:RNSearchWindowCreateNewItemString];
    [self setMenuExtras:extras];
    rowCount += [extras count];
    [self setTableRows:rowCount];
}


#pragma mark -
#pragma mark Search field delegate methods

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command {
    if (command == @selector(moveUp:)) {
        NSInteger newRow = [[self searchMenu] selectedRow] - 1;
        if ([[self searchMenu] isSeparatorAtIndex:newRow])
            newRow--;
        if ([[self searchMenu] isValidIndex:newRow])
            [[self searchMenu] setSelectedRow:newRow];
        return YES;
    }
    if (command == @selector(moveDown:)) {
        NSInteger newRow = [[self searchMenu] selectedRow] + 1;
        if ([[self searchMenu] isSeparatorAtIndex:newRow])
            newRow++;
        if ([[self searchMenu] isValidIndex:newRow])
            [[self searchMenu] setSelectedRow:newRow];
        return YES;
    }
    if (command == @selector(insertNewline:)) {
        [self addSelectedItem_];
        return YES;
    }
    if (command == @selector(cancelOperation:)) {
        [[self searchField] setStringValue:@""];
        [self searchStringChanged:nil]; 
        return YES;
    }
    
    return NO;
}

- (void)controlTextDidEndEditing:(NSNotification *)aNotification {
    [self removeSearchMenu_];
}


#pragma mark -
#pragma mark Search menu datasource methods

-(NSUInteger)numberOfItemsInMenu {
    return [self tableRows];
}

-(id)itemTitleAtIndex:(NSUInteger)itemIndex {
    NSInteger itemCount = [[[self filteredItemsArrayController] arrangedObjects] count];
    if (itemIndex < itemCount)
        return [[[[self filteredItemsArrayController] arrangedObjects] objectAtIndex:itemIndex] valueForKey:RNTitleKey];
    itemIndex -= itemCount;
    NSInteger extrasCount = [[self menuExtras] count];
    if (itemIndex < extrasCount)
        return [[self menuExtras] objectAtIndex:itemIndex];
        
    return nil;
}

@end